注册

浅析Easy-ARMi.MAX283 GPIO中断驱动模块
首页 > 嵌入式开发 > Linux嵌入式    作者:RainFly   2016年3月20日 21:46 星期日   热度:9714°   字号:   评论:1    
时间:2016-3-20 21:46   热度:9714°  评论:1 条 

需要的是一步步解析这个代码中比较抽象难懂的点 顺带举一反三 共同学习 不喜勿喷!

贴上源代码 在光盘文件 ....\3.Linux\4.开发示例6、驱动示例GPIO中断

#inc lude<linux/init.h>

#include<linux/module.h>
#include<mach/gpio.h>                                                  
#include<asm/io.h>                                                 
#include"mach/../../mx28_pins.h"
#include <mach/pinctrl.h>
#include "mach/mx28.h"
#include<linux/fs.h>
#include <linux/io.h>
#include<asm/uaccess.h>                                     
#include<linux/miscdevice.h>                          
#include<linux/irq.h>                          
#include<linux/sched.h>                   
#include<linux/interrupt.h>              
#include<linux/timer.h>

#include <linux/kernel.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>


#define GPIO_BUTTON_PIN PINID_SSP0_DATA4 //按键的引脚为P2.4

//具体引脚文件的配置在内核arch/arm/mach-mx28/mx28_pin.h文件中宏定义添加引脚配置 

QQ图片20160320222509.png

MXS_PING_ENCODE函数是通过计算得出引脚位置

#define MXS_PIN_ENCODE(b, p)   \
((((b) & MXS_PIN_BANK_MAX) << MXS_PIN_BANK_BIT) |\
((p) & MXS_PIN_PINID_MAX))
 

static volatile int ev_press = 0;

static struct fasync_struct *button_async;

struct pin_desc_s{ //中断引脚描述结构体
unsigned int pin;
unsigned int irq;
unsigned int key_val;
};
static unsigned char key_val;
//初始化中断引脚结构体
struct pin_desc_s pin_desc = {
.pin     = MXS_PIN_TO_GPIO(GPIO_BUTTON_PIN),
.key_val = 0,
};
static DECLARE_MUTEX(button_lock);     
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

//中断处理函数
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
struct pin_desc_s * pindesc = (struct pin_desc_s *)dev_id;
unsigned int pinval;

pinval = gpio_get_value(pindesc->pin);

if (pinval)
{
key_val = 1;
}
else
{
key_val = pindesc->key_val;
}
        ev_press = 1;
        wake_up_interruptible(&button_waitq); //唤醒等待队列里面的进程
kill_fasync (&button_async, SIGIO, POLL_IN); //异步通知
//printk("interrupt occur..........\n");
return IRQ_RETVAL(IRQ_HANDLED);
}

static int gpio_drv_open(struct inode *inode, struct file *file)
{
int iRet=0;

if (file->f_flags & O_NONBLOCK)
{
if (down_trylock(&button_lock))
return -EBUSY;
}
else
{
down(&button_lock);
}
gpio_direction_input(pin_desc.pin);
pin_desc.irq = gpio_to_irq(pin_desc.pin); 
if (pin_desc.irq) 
disable_irq(pin_desc.irq);
set_irq_type(pin_desc.irq, IRQF_TRIGGER_FALLING); //下降沿中断
//申请中断并设置中断处理函数
iRet = request_irq(pin_desc.irq, buttons_irq, IRQF_SHARED, "gpio_int", &pin_desc);
if (iRet != 0){
printk("request irq failed!! ret: %d  irq:%d \n", iRet,pin_desc.irq);
return -EBUSY;
}
return 0;
}

ssize_t gpio_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
if (size != 1)
return -EINVAL;

if (file->f_flags & O_NONBLOCK)
{
if (!ev_press)
return -EAGAIN;
}
else
{
wait_event_interruptible(button_waitq, ev_press);
}
copy_to_user(buf, &key_val, 1);
ev_press = 0;

return 1;
}

int gpio_drv_close(struct inode *inode, struct file *file)
{
free_irq(pin_desc.irq, &pin_desc);
up(&button_lock);
return 0;
}

static int gpio_drv_fasync (int fd, struct file *filp, int on)
{
printk("driver: gpio_drv_fasync\n");
return fasync_helper (fd, filp, on, &button_async);
}

static struct file_operations gpio_drv_fops = {
.owner = THIS_MODULE,
.open = gpio_drv_open,
.read = gpio_drv_read,
.release = gpio_drv_close,
.fasync = gpio_drv_fasync,
};

static struct miscdevice button_miscdev = 
{
.minor        = MISC_DYNAMIC_MINOR,
    .name        = "magic-gpio",
    .fops        = &gpio_drv_fops,
};

static int __init gpio_drv_init(void)
{
int iRet=0;
printk("gpio_miscdev module init!\n");

iRet = misc_register(&button_miscdev);

// 注册miscdevice 混杂设备驱动 公用主设备号为10,节省主设备号!  

详细解释 http://blog.csdn.net/tong646591/article/details/8301925

if (iRet) {
printk("register failed!\n");

return 0;
}

static void __exit gpio_drv_exit(void)
{
printk("gpio_miscdev module exit!\n");
misc_deregister(&button_miscdev);
}

module_init(gpio_drv_init);
module_exit(gpio_drv_exit);

MODULE_AUTHOR("EasyARM283 By LZZ");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("gpio button interrupt module");

  您阅读这篇文章共花了:  
捐赠支持:如果觉得这篇文章对您有帮助,请 "扫一扫"鼓励作者!
二维码加载中...
本文作者:RainFly      文章标题: 浅析Easy-ARMi.MAX283 GPIO中断驱动模块
本文地址:http://www.rainfly.cn/?post=179
版权声明:若无注明,本文皆为“雨夜轩”原创,转载请保留文章出处。

还有小板凳哦!

手工活赚钱  Google Chrome 63.0.3239.132 Google Chrome 63.0.3239.132 Windows 7 Windows 7  2019-04-11 09:44 沙发
感谢博主分享。

QQ游客评论

返回顶部    首页    捐赠支持    手气不错    友情链接    关于我们    站长工具    站长介绍    手机版本    后台登陆   
版权所有:雨夜轩    站长:RainFly    特别鸣谢   文章归档   皖ICP备15003600号-1   百度统计
Copyright©2015 雨夜轩 Powered by emlog强力驱动 七牛CDN全球加速 360站长联盟安全认证 中国博客联盟荣誉成员 可信赖网站 站点地图   
页面加载耗时:0.038秒 数据库查询次数:13次
背景设置